Android - Behavior
Apr 1, 2017
Behaivor
Behavior只有是CoordinatorLayout的直接子View才有意义。只要将Behavior绑定到CoordinatorLayout的直接子元素上,就能对触摸事件(touch events)、window insets、measurement、layout以及嵌套滚动(nested scrolling)等动作进行拦截。Design Library的大多功能都是借助Behavior的大量运用来实现的。当然,Behavior无法独立完成工作,必须与实际调用的CoordinatorLayout子视图相绑定。具体有三种方式:通过代码绑定、在XML中绑定或者通过注释实现自动绑定。上面NestedScrollView中app:layout_behavior=”@string/appbar_scrolling_view_behavior”的Behavior是系统默认的,我们也可以根据自己的需求来自定义Behavior。
自定义Behavior
- 某个view监听另一个view的状态变化,例如大小、位置、显示状态等
需要关系:layoutDependsOn和onDependentViewChanged方法, - 某个view监听CoordinatorLayout里的滑动状态
需要关系:onStartNestedScroll和onNestedPreScroll方法123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124/*** 表示是否给应用了Behavior 的View 指定一个依赖的布局,通常,当依赖的View 布局发生变化时* 不管被被依赖View 的顺序怎样,被依赖的View也会重新布局* @param parent* @param child 绑定behavior 的View* @param dependency 依赖的view* @return 如果child 是依赖的指定的View 返回true,否则返回false*/public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {return super.layoutDependsOn(parent, child, dependency);}/*** 当被依赖的View 状态(如:位置、大小)发生变化时,这个方法被调用* @param parent* @param child* @param dependency* @return*/public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {return super.onDependentViewChanged(parent, child, dependency);}/*** 当coordinatorLayout 的子View试图开始嵌套滑动的时候被调用。当返回值为true的时候表明* coordinatorLayout 充当nested scroll parent 处理这次滑动,需要注意的是只有当返回值为true* 的时候,Behavior 才能收到后面的一些nested scroll 事件回调(如:onNestedPreScroll、onNestedScroll等)* 这个方法有个重要的参数nestedScrollAxes,表明处理的滑动的方向。** @param coordinatorLayout 和Behavior 绑定的View的父CoordinatorLayout* @param child 和Behavior 绑定的View* @param directTargetChild* @param target* @param nestedScrollAxes 嵌套滑动 应用的滑动方向,看 {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},* {@link ViewCompat#SCROLL_AXIS_VERTICAL}* @return*/public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);}/*** 嵌套滚动发生之前被调用* 在nested scroll child 消费掉自己的滚动距离之前,嵌套滚动每次被nested scroll child* 更新都会调用onNestedPreScroll。注意有个重要的参数consumed,可以修改这个数组表示你消费* 了多少距离。假设用户滑动了100px,child 做了90px 的位移,你需要把 consumed[1]的值改成90,* 这样coordinatorLayout就能知道只处理剩下的10px的滚动。* @param coordinatorLayout* @param child* @param target* @param dx 用户水平方向的滚动距离* @param dy 用户竖直方向的滚动距离* @param consumed*/public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);}/*** 进行嵌套滚动时被调用* @param coordinatorLayout* @param child* @param target* @param dxConsumed target 已经消费的x方向的距离* @param dyConsumed target 已经消费的y方向的距离* @param dxUnconsumed x 方向剩下的滚动距离* @param dyUnconsumed y 方向剩下的滚动距离*/public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);}/*** 嵌套滚动结束时被调用,这是一个清除滚动状态等的好时机。* @param coordinatorLayout* @param child* @param target*/public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {super.onStopNestedScroll(coordinatorLayout, child, target);}/*** onStartNestedScroll返回true才会触发这个方法,接受滚动处理后回调,可以在这个* 方法里做一些准备工作,如一些状态的重置等。* @param coordinatorLayout* @param child* @param directTargetChild* @param target* @param nestedScrollAxes*/public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {super.onNestedScrollAccepted(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);}/*** 用户松开手指并且会发生惯性动作之前调用,参数提供了速度信息,可以根据这些速度信息* 决定最终状态,比如滚动Header,是让Header处于展开状态还是折叠状态。返回true 表* 示消费了fling.** @param coordinatorLayout* @param child* @param target* @param velocityX x 方向的速度* @param velocityY y 方向的速度* @return*/public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) {return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY);}//可以重写这个方法对子View 进行重新布局public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {return super.onLayoutChild(parent, child, layoutDirection);}